package connection;

import gui.Desktop;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PipedInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;

import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;

/**
 * Trida slouzici jako parser pro sought infoemace ze serveru
 * 
 * @author dove
 * 
 */
public class Sought implements Runnable {

	private DefaultTableModel model;
	private PipedInputStream br;
	private BufferedWriter bw;
	private Thread sought;
	private boolean running = false;
	private String word = "";
	private int letter = 0;
	private Object[] newRow;
	private int game;

	private List<Integer> games;
	private Preferences prefs;
	private ResourceBundle messages;
	private static Logger logger = Logger.getLogger("Log");

	/**
	 * Pripojeni a spusteni vlakna
	 * 
	 * @param model
	 *            model do ktereho chceme vypisovat informace
	 * @param table
	 *            tabulka JTable
	 */
	public Sought(final DefaultTableModel model, final JTable table) {
		this.model = model;
		newRow = new Object[8];
		games = new ArrayList<Integer>();

		table.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					public void valueChanged(ListSelectionEvent event) {
						ListSelectionModel ls = (ListSelectionModel) event
								.getSource();
						if (!ls.isSelectionEmpty()) {

							table.getSelectionModel().clearSelection();
							writeCom("play "
									+ table.getValueAt(table
											.getSelectionModel()
											.getLeadSelectionIndex(), 0) + "\n");
						}
					}
				});
		prefs = Preferences.userRoot();
		String language = prefs.get("Language", "en");
		Locale currentLocale = new Locale(language);
		messages = ResourceBundle.getBundle("Lang", currentLocale);
	}

	/**
	 * Pripojeni k Readeru
	 */
	public void connect() {
		br = Reader.getReader("Sought");
		bw = Reader.getWriter();
		running = true;
		sought = new Thread(this);
		sought.start();
	}

	/**
	 * Metoda pro zapis prikazu na server
	 * 
	 * @param com
	 *            prikaz
	 */
	public void writeCom(String com) {
		try {
			bw.write(com);
			bw.flush();
		} catch (IOException e) {
			logger.error("", e);
		}
	}

	/**
	 * Odebira z modelu nabidku hry
	 * 
	 * @param lineNumber
	 *            cislo radku ktery chceme z modelu odebrat
	 */
	private synchronized void removeGame(int lineNumber) {
		games.remove(lineNumber);
		model.removeRow(lineNumber);
	}

	public void run() {
		Reader.setReading("Sought");
		while (running) {
			if (!Reader.isConnect()) {
				running = false;
			}
			try {
				if (Reader.isConnect()) {
					letter = br.read();
				} else {
					return;
				}
			} catch (Exception e) {
				// logger.error("", e);
				e.printStackTrace();
			}
			if (letter != 13) {
				word = word.concat(String.valueOf((char) letter));
			}
			if (letter == ' ' || letter == 10) {
				word = "";
			}
			if (word.equals("<s>")) {
				word = "";
				while (letter != 13) {
					try {
						letter = br.read();
					} catch (Exception e) {
						logger.error("", e);
					}
					word = word.concat(String.valueOf((char) letter));
				}
				StringTokenizer token = new StringTokenizer(word);
				game = Integer.valueOf(token.nextToken());
				newRow[0] = game;
				newRow[1] = token.nextToken().substring(2);
				token.nextToken();
				String rating = token.nextToken().substring(3);
				if (rating.charAt(rating.length() - 1) == 'E'
						|| rating.charAt(rating.length() - 1) == 'P') {
					rating = rating.substring(0, rating.length() - 1);
				}
				newRow[2] = new Integer(rating);
				newRow[3] = Integer.valueOf(token.nextToken().substring(2));
				newRow[4] = token.nextToken().substring(2);
				String rated = token.nextToken().substring(2);
				if (rated.equals("r")) {
					rated = "rated";
				} else {
					rated = "unrated";
				}
				newRow[5] = rated;
				newRow[6] = token.nextToken().substring(3);
				newRow[7] = token.nextToken().substring(2);
				model.addRow(newRow);
				games.add(game);
				word = "";
			} else if (word.equals("<sr>")) {
				word = "";
				while (letter != 13) {
					try {
						letter = br.read();
					} catch (Exception e) {
						logger.error("", e);
					}
					word = word.concat(String.valueOf((char) letter));
				}
				StringTokenizer token = new StringTokenizer(word);
				while (token.hasMoreTokens()) {
					game = Integer.valueOf(token.nextToken());
					for (int x = 0; x < games.size(); x++) {
						if (game == games.get(x)) {
							removeGame(x);
						}
					}
				}
				word = "";
			}
			if (word.equals("Creating:")) {
				logger.debug("ODEBIRANI ZE SOUGHT LISTU");
				for (int x = games.size() - 1; x > -1; x--) {
					removeGame(x);
				}
				model.fireTableDataChanged();
			}
			if (word.equals("{Game")) {
				logger.debug("KONEC HRY");
				games.clear();
				logger.debug("Seznam prazdny2");
				writeCom("iset seekinfo 1 \n");
			}
			if (word.equals("Challenge:")) {
				word = "";
				do {
					word = word.concat("<br/>");
					while (letter != 13) {
						try {
							letter = br.read();
						} catch (Exception e) {
							logger.error("", e);
						}
						word = word.concat(String.valueOf((char) letter));
					}
					letter = 0;
				} while (!word.substring(word.length() - 13, word.length() - 2)
						.equals("parameters."));
				Desktop
						.chalenge("<html><CENTER><b>"
								+ messages.getString("Chalenge")
								+ "</b></CENTER><br/><br/>" + word
								+ "</CENTER></html>");
			}
		}
	}
}
